import os
import random
import logging
import numpy as np
import imageio.v3 as iio
import os
import matplotlib.pyplot as plt
import pandas as pd

import multi_beam.multi_beam_NN
import multi_beam.multi_beam_PS
import multi_beam.multi_beam_QR
import multi_beam.multi_beam_QE
import multi_beam.multi_beam_GA_QE

from util.util_log import setup_logging
from util.util_csv import read_csv_to_numpy_array

from multi_beam.analysis_result_mutil_beam import multi_beam_psll_peaks


# 配置日志，默认打印到控制台，也可以设置打印到文件
setup_logging()
# setup_logging(log_file="../../files/logs/log_analysis_multi_beam.log")
# 获取日志记录器并记录日志
logger = logging.getLogger("[analysis][RIS-multi-beam]")


# 读取CSV文件的第一列数据
def read_csv_peak(path_csv):
    # 读取CSV文件
    data = pd.read_csv(path_csv)
    # 获取第一列的数据
    first_column_data = data.iloc[:, 0]  # 使用iloc获取第一列的数据
    return first_column_data


# 绘制折线图
def plot_first_column_and_get_max(datas):
    plt.figure(figsize=(10, 5))
    plt.plot(datas, marker='o')
    # plt.title('Line Chart of First Column')
    plt.xlabel('Index')
    plt.ylabel('PSL max (dB)')
    plt.grid(True)
    plt.show()


# 波束方向图生成动图
def create_gif(image_folder, output_file, duration):
    # 获取文件夹下所有的jpg文件
    images = [f for f in os.listdir(image_folder) if f.endswith('.jpg')]
    # 按照文件名排序
    images.sort()
    # 读取所有图片
    frames = [iio.imread(os.path.join(image_folder, img)) for img in images]
    # 写入GIF文件
    iio.imwrite(output_file, frames, extension=".gif", loop=0, fps=1/duration)


# ======================================================== 流程 =================================================
def generate_random_beams(beam_num, bit_num):
    # 第一个数范围[0, 90]，第二个数范围[0, 360]
    beams = []
    for _ in range(beam_num):
        first_number = random.randint(0, 90)
        second_number = random.randint(0, 360)
        beams.append([first_number, second_number])
    # 打印生成的数
    logger.info(f"Generated {beam_num} beams: {beams}")
    return beams


def save_beams_to_file(beams, filename):
    """将波束指向保存到文件中"""
    with open(filename, 'w') as file:
        for beam in beams:
            file.write(','.join(map(str, beam)) + '\n')


def load_beams_from_file(filename):
    """从文件中加载波束指向"""
    beams = []
    with open(filename, 'r') as file:
        for line in file:
            beam = list(map(int, line.strip().split(',')))
            beams.append(beam)
    return beams


def create_dir(folder_path):
    # 创建文件夹
    try:
        os.makedirs(folder_path, exist_ok=True)
        logger.info(f"success created folder: {folder_path}")
    except Exception as e:
        logger.error(f"Failed to create folder: {e}")
        return


def write_pattern_peaks(name, path_csv, path_result):
    # 读码阵.csv
    phase = read_csv_to_numpy_array(path_csv)
    # 算峰值
    peaks = multi_beam_psll_peaks(phase)
    # 写记录
    peaks = peaks[:20]
    with open(path_result, 'a') as file:
        for i in range(len(peaks)):
            peak = peaks[i]
            file.write("[%s]%d: %4f (%d, %d)\n" % (name, i, peak[0], peak[1][0], peak[1][1]))


# ======================================================== 主函数 ===============================================
# 波束方向图生成动图
def multi_beam_scan_gif():
    # 保存gif
    create_gif("../../files/multi-beam-scan/PS/4-(30,30,0,-20,20,10,30,30,0,70,110,10,30,30,0,160,200,10,30,30,0,250,290,10)/patternBit_mix_xyz",
               "../../files/multi-beam-scan/PS/4-(30,30,0,-20,20,10,30,30,0,70,110,10,30,30,0,160,200,10,30,30,0,250,290,10)/patternBit_mix_xyz.gif",
               0.2)  # duration 是每帧显示的时间，单位是秒

#
def multi_beam_scan_peak_img():
    path_csv = "../../files/multi-beam-scan/PS/4-(30,30,0,-20,20,10,30,30,0,70,110,10,30,30,0,160,200,10,30,30,0,250,290,10)/list_peak_5th.csv"
    first_column_data = read_csv_peak(path_csv)
    # 返回第一列的最大值
    max_value = first_column_data.max()
    print("max_value:", max_value)
    plot_first_column_and_get_max(first_column_data)


# ------------------------------------------------- 以下是多波束随机多波束 -------------------------------------------------
# 随机N波束 (PS, QR, QE)
def multi_beam_scan_rand_N(beam_num, bit_num, path_pre):
    path_beams = path_pre + "beams.txt"
    path_result = path_pre + "result.txt"
    logger.info("path_beams: %s, path_result: %s" % (path_beams, path_result))
    # 0. 检查波束指向的文件 beams.txt
    if not os.path.exists(path_beams):
        # 生成 N 个随机波束指向
        beams = generate_random_beams(beam_num, bit_num)
        # 保存 beams.txt
        save_beams_to_file(beams, path_beams)
    else:
        # 加载现有的波束指向
        beams = load_beams_from_file(path_beams)
    # 1. 生成各种方法 dir
    path_pre_PS = os.path.join(path_pre, "PS") + "/"
    path_pre_QR = os.path.join(path_pre, "QR") + "/"
    path_pre_QE = os.path.join(path_pre, "QE") + "/"
    path_pre_GA_QE = os.path.join(path_pre, "GA_QE") + "/"
    logger.info("path_pre_PS: %s" % path_pre_PS)
    logger.info("path_pre_QR: %s" % path_pre_QR)
    logger.info("path_pre_QE: %s" % path_pre_QE)
    logger.info("path_pre_GA_QE: %s" % path_pre_GA_QE)
    create_dir(path_pre_PS)
    create_dir(path_pre_QR)
    create_dir(path_pre_QE)
    create_dir(path_pre_GA_QE)
    # 2. 各种方法测试多波束并保存结果
    logger.info("beams: %s" % str(beams))
    multi_beam.multi_beam_PS.main_multi_beam_N(beams, path_pre_PS, bit_num)
    multi_beam.multi_beam_QR.main_multi_beam_N(beams, path_pre_QR, bit_num)
    multi_beam.multi_beam_QE.main_multi_beam_N(beams, path_pre_QE, bit_num)
    # 特殊处理 NN
    if beam_num in [2, 4, 8, 16]:
        path_pre_NN = os.path.join(path_pre, "NN") + "/"
        logger.info("path_pre_NN: %s" % path_pre_NN)
        create_dir(path_pre_NN)
        if beam_num == 2:
            multi_beam.multi_beam_NN.main_multi_beam_2(beams[0][0], beams[0][1], beams[1][0], beams[1][1],
                                                       path_pre_NN, bit_num)
        elif beam_num == 4:
            multi_beam.multi_beam_NN.main_multi_beam_4(beams[0][0], beams[0][1], beams[1][0], beams[1][1],
                                                       beams[2][0], beams[2][1], beams[3][0], beams[3][1],
                                                       path_pre_NN, bit_num)
        elif beam_num == 8:
            multi_beam.multi_beam_NN.main_multi_beam_8_cub(beams[0][0], beams[0][1], beams[1][0], beams[1][1],
                                                           beams[2][0], beams[2][1], beams[3][0], beams[3][1],
                                                           beams[4][0], beams[4][1], beams[5][0], beams[5][1],
                                                           beams[6][0], beams[6][1], beams[7][0], beams[7][1],
                                                           path_pre_NN, bit_num)
        elif beam_num == 16:
            multi_beam.multi_beam_NN.main_multi_beam_16_cub(beams[0][0], beams[0][1], beams[1][0], beams[1][1],
                                                            beams[2][0], beams[2][1], beams[3][0], beams[3][1],
                                                            beams[4][0], beams[4][1], beams[5][0], beams[5][1],
                                                            beams[6][0], beams[6][1], beams[7][0], beams[7][1],
                                                            beams[8][0], beams[8][1], beams[9][0], beams[9][1],
                                                            beams[10][0], beams[10][1], beams[11][0], beams[11][1],
                                                            beams[12][0], beams[12][1], beams[13][0], beams[13][1],
                                                            beams[14][0], beams[14][1], beams[15][0], beams[15][1],
                                                            path_pre_NN, bit_num)
    # 3. 生成综合结果 result.txt
    # write_pattern_peaks("PS-" + str(beam_num) + "-rand", path_pre_PS + "phaseBit_mix.csv", path_result)
    # write_pattern_peaks("QR-" + str(beam_num) + "-rand", path_pre_QR + "phase_mix.csv", path_result)
    # write_pattern_peaks("QE-" + str(beam_num) + "-rand", path_pre_QE + "phase_mix.csv", path_result)


# ============================================ main ===============================================
def main():
    # 生成动图
    # multi_beam_scan_gif()
    # multi_beam_scan_peak_img()
    multi_beam_scan_rand_N(2, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-2/")
    multi_beam_scan_rand_N(4, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-4/")
    multi_beam_scan_rand_N(8, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-8/")
    multi_beam_scan_rand_N(16, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-16/")
    #
    multi_beam_scan_rand_N(1, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-1/")
    multi_beam_scan_rand_N(3, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-3/")
    multi_beam_scan_rand_N(5, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-5/")
    multi_beam_scan_rand_N(6, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-6/")
    multi_beam_scan_rand_N(7, 1, f"E://project/ant_sim/files/multi-beam-scan/1bit/rand-7/")




if __name__ == '__main__':
    logger.info("[analysis][RIS-multi-beam]: analysis")
    # 主函数
    main()